﻿using System;
using System.Collections.Generic;

namespace Core
{
    public class EventSystem
    {
        private readonly Queue<IObject>[] queues = new Queue<IObject>[InstanceQueueIndex.Max];

        public EventSystem()
        {
            queues[InstanceQueueIndex.Update] = new Queue<IObject>();
            queues[InstanceQueueIndex.FixedUpdate] = new Queue<IObject>();
        }

        public void RegisterSystem(IObject eventObject)
        {
            if(eventObject is IUpdate)
            {
                queues[InstanceQueueIndex.Update].Enqueue(eventObject);
            }

            if(eventObject is IFixedUpdate)
            {
                queues[InstanceQueueIndex.FixedUpdate].Enqueue(eventObject);
            }
        }

        public void Update()
        {
            var queue = this.queues[InstanceQueueIndex.Update];
            int count = queue.Count;
            while (count-- > 0)
            {
                var eventObject = queue.Dequeue();
                if (eventObject == null)
                    continue;

                if (eventObject.IsDisposed)
                    continue;

                if (eventObject is not IUpdate)
                    continue;

                queue.Enqueue(eventObject);
                try
                {
                    (eventObject as IUpdate).Update();
                }
                catch(Exception ex)
                {
                    Log.Error(ex);
                }
            }
        }

        public void FixedUpdate()
        {
            var queue = this.queues[InstanceQueueIndex.FixedUpdate];
            int count = queue.Count;
            while (count-- > 0)
            {
                var eventObject = queue.Dequeue();
                if (eventObject == null)
                    continue;

                if (eventObject.IsDisposed)
                    continue;

                if (eventObject is not IFixedUpdate)
                    continue;

                queue.Enqueue(eventObject);
                try
                {
                    (eventObject as IFixedUpdate).FixedUpdate();
                }
                catch (Exception ex)
                {
                    Log.Error(ex);
                }
            }
        }
    }
}
